using System;
using System.Collections;

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.EnhancedTouch;
using UnityEngine.InputSystem.Interactions;

namespace Miya.InputController
{

    public class InputController : MonoBehaviour
    {

        [Header("开启滚动")]
        public bool enableZoom = true;
        [Header("滚动系数，在手势时有效")]
        public float zoomFactor = 0.1f;

        [Header("拖动系数，在手势时有效")]
        public float DragFactor =1;

        [Header("开启点击，同时控制单击，双击，拖拽")]
        public bool enableClick = true;
        [Tooltip("必须开启点击才能有效")]
        public bool enableDoubleClick = true;
        [Tooltip("必须开启点击才能有效")]
        public bool enableDrag = true;

        [Header("开启旋转")]
        public bool enableRotation = true;

        [Header("是否输出日志")]
        public bool EnableLog = false;

        private InputActionManager _InputActionManager;
        private InputAction _TapAction;
        private InputAction _ZoomAction;
        private InputAction _KeyRotationAction;
        private InputAction _TouchContactAction;
        private bool draging;
        private Coroutine zoomCoroutine;

        private Coroutine rotationCoroutine;

        public static InputController INSTANCE;
        private void Awake()
        {
            INSTANCE = this;
            if (_InputActionManager == null) _InputActionManager = new InputActionManager();
            _InputActionManager.Enable();
            EnhancedTouchSupport.Enable();
            _TapAction = _InputActionManager.GameCtrl.Tap;
            _ZoomAction = _InputActionManager.GameCtrl.Zoom;
            _KeyRotationAction = _InputActionManager.GameCtrl.Rotation;
            _TouchContactAction = _InputActionManager.GameCtrl.SecondaryTouchContact;
            if(EnableLog) Debug.Log($"[InputController Awake...]...");
        }
        void OnEnable()
        {
            if (_InputActionManager != null) _InputActionManager.Enable();

            //Debug.Log($"[InputController Enable...]..." + _InputActionManager != null ? "Input Enable" : "Input Disable");
        }
        private void Start()
        {
            if (EnableLog) Debug.Log($"[InputController Start...]...");
            if (enableClick)
            {
                _TapAction.performed += ctx =>
                {
                    if (ctx.interaction is HoldInteraction)
                    {
                        if (EnableLog) Debug.Log($"[InputController TapAction ...] Is Hold");
                        if (Input.touchCount > 1)
                        {
                            return;
                        }
                        draging = true;
                        if (EnableLog) Debug.Log($"[InputController TapAction ...] draging = true");
                        DoDrag();
                    }
                    else if (ctx.interaction is MultiTapInteraction)
                    {
                        draging = false;
                        if (_OnDoubleClick != null)
                        {
                            _OnDoubleClick.Invoke(GetCurrentPosition());
                        }
                    }
                };

                _TapAction.canceled += ctx =>
                {
                    draging = false;
                    DoEndDrag();
                    if (ctx.interaction is MultiTapInteraction)
                    {
                        if (_OnClick != null)
                        {
                            _OnClick.Invoke(GetCurrentPosition());
                        }
                    }
                };
            }

            if (enableZoom || enableRotation)
            {
                //鼠标缩放
                if (enableZoom)
                {
                    _ZoomAction.performed += ctx =>
                    {
                        draging = false;
                        var distance = ctx.ReadValue<float>();
                        if (_OnZoom != null)
                        {
                            Vector2 focus = Input.mousePosition;
                            _OnZoom.Invoke(distance / 120f, focus);
                        }
                    };
                }
                //键盘滚动
                if (enableRotation)
                {
                    _KeyRotationAction.started += ctx =>
                    {
                        draging = false;
                        if (EnableLog) Debug.Log("[InputController Rotation Start]");
                        rotationCoroutine = StartCoroutine(RotationDetection());

                    };
                    _KeyRotationAction.canceled += ctx =>
                    {
                        if (EnableLog) Debug.Log("[InputController Rotation Cancel]");
                        StopCoroutine(rotationCoroutine);
                    };
                }

                _TouchContactAction.started += ctx => TouchZoomStart();

                _TouchContactAction.canceled += ctx => TouchZoomEnd();
            }
        }

        IEnumerator RotationDetection()
        {
            while (true)
            {
                if (EnableLog) Debug.Log("[InputController RotationDetection]");
                if (enableRotation && _OnRotation != null)
                {
                    var _rotateSpeed = 50f;
                    float rotateDirection = _InputActionManager.GameCtrl.Rotation.ReadValue<float>();
                    var angle = Time.deltaTime * _rotateSpeed * rotateDirection;
                    _OnRotation.Invoke(angle);
                }
                yield return null;
            }
        }

        private void TouchRotationEnd()
        {
            if (EnableLog) Debug.Log("[InputController Rotation Cancel]");
            StopCoroutine(rotationCoroutine);
        }

        private void TouchRotationStart()
        {
            if (EnableLog) Debug.Log("[InputController Rotation Start]");
            rotationCoroutine = StartCoroutine(TouchRotationDetection());
        }

        IEnumerator TouchRotationDetection()
        {
            while (true)
            {
                if (EnableLog) Debug.Log("[InputController RotationDetection]");
                var _rotateSpeed = 50f;
                float rotateDirection = _InputActionManager.GameCtrl.Rotation.ReadValue<float>();
                transform.Rotate(Vector3.left * Time.deltaTime * _rotateSpeed * rotateDirection);
                yield return null;
            }
        }

        private void TouchZoomEnd()
        {
            if (EnableLog) Debug.Log("[InputController Touch End...]");
            StopCoroutine(zoomCoroutine);
        }

        private void TouchZoomStart()
        {
            draging = false;
            if (EnableLog) Debug.Log("[InputController Touch Start...]");
            zoomCoroutine = StartCoroutine(TouchZoomDetection());
        }

        IEnumerator TouchZoomDetection()
        {
            float distance = 0, predistance = 0;
            Vector2 prePrimaryPosition = Vector2.zero, preSecondaryPosition = Vector2.zero;
            Vector2 primaryPosition = Vector2.zero, secondaryPosition = Vector2.zero;

            while (true)
            {
                primaryPosition = _InputActionManager.GameCtrl.PrimaryFingerPosition.ReadValue<Vector2>();
                secondaryPosition = _InputActionManager.GameCtrl.SecondaryFingerPosition.ReadValue<Vector2>();
                distance = Vector3.Distance(primaryPosition, secondaryPosition);

                if (EnableLog) Debug.Log($"[Input Controller TouchZoomDetection Pos]...{primaryPosition}...{secondaryPosition}");

                if (enableRotation && _OnRotation != null)
                {
                    Vector2 curDir = secondaryPosition - primaryPosition;
                    Vector2 oldDir = preSecondaryPosition - prePrimaryPosition;
                    float angle = Vector2.Angle(oldDir, curDir);
                    angle *= Mathf.Sign(Vector3.Cross(oldDir, curDir).z);
                    _OnRotation.Invoke(angle);
                }

                if (_OnZoom != null)
                {
                    Vector2 focus = (primaryPosition + secondaryPosition) * 0.5f;

                    float delta = predistance == 0 ? 0 : (distance - predistance) * zoomFactor;
                    if (EnableLog) Debug.Log($"[Input Controller TouchZoomDetection]...{delta}...{focus}");
                    _OnZoom.Invoke(delta, focus);
                }
                predistance = distance;
                prePrimaryPosition = primaryPosition;
                preSecondaryPosition = secondaryPosition;
                yield return null;
            }
        }

        private void DoDrag()
        {
            if (_OnDrag != null || _OnDragEx!=null)
            {
                var delt = _InputActionManager.GameCtrl.TapDelta.ReadValue<Vector2>();
                var mpos = _InputActionManager.GameCtrl.PrimaryFingerPosition.ReadValue<Vector2>();
                //Debug.Log($"Current:{currentPos}.");
                if (EnableLog) Debug.Log($"[Input Controller DoDrag]:delt={delt}");
                if(delt.x != 0 || delt.y != 0 )
                {
                    delt *= DragFactor;
                    _OnDrag?.Invoke(delt);
                    _OnDragEx?.Invoke(delt, mpos);
                }
 
            }


        }

        private void DoEndDrag()
        {
            if(_OnDragEnd != null)
            {
                _OnDragEnd.Invoke();
            }
        }

        Vector2 GetCurrentPosition()
        {
            if (Mouse.current != null)
            {
                return Mouse.current.delta.ReadValue();
            }
            else if (Touchscreen.current != null)
            {
                return Touchscreen.current.delta.ReadValue();
            }
            return Vector2.zero;
        }

        // Update is called once per frame
        void Update()
        {
            if (draging)
            {
                DoDrag();
            }
        }

        private Action<Vector3> _OnClick;
        public InputController WaitClick(Action<Vector3> on)
        {
            _OnClick = on;
            return this;
        }
        private Action<Vector3> _OnDoubleClick;
        public InputController WaitDoubleClick(Action<Vector3> on)
        {
            _OnDoubleClick = on;
            return this;
        }

        private Action<Vector2> _OnDrag;
        public InputController WaitDrag(Action<Vector2> on)
        {
            _OnDrag = on;
            return this;
        }

        private Action<Vector2, Vector2> _OnDragEx;
        public InputController WaitDrag(Action<Vector2, Vector2> on)
        {
            _OnDragEx = on;
            return this;
        }

        private Action _OnDragEnd;
        public InputController WaitDragEnd(Action on)
        {
            _OnDragEnd = on;
            return this;
        }

        private Action<float,Vector2> _OnZoom;
        public InputController WaitZoom(Action<float, Vector2> on)
        {
            _OnZoom = on;
            return this;
        }

        private Action<float> _OnRotation;
        public InputController WaitRotation(Action<float> on)
        {
            _OnRotation = on;
            return this;
        }
        private void OnDisable()
        {
            if (_InputActionManager != null) _InputActionManager.Disable();
            //Debug.Log($"[InputController Disable...]...");
        }
    }
}


